#include<iostream>
#include<unistd.h>
#include<fcntl.h>
#include<cerrno>
#include<string.h>
using namespace std;

bool SetNonBlock(int fd)//将指定的文件描述符设置为非阻塞
{
    int fl = fcntl(fd,F_GETFL);//获取fd原有的设置选项，我们只想更改非阻塞状态，其余的内容不做修改
    if(fl<0)
    {
        //获取失败
        return false;
    }
    fcntl(fd,F_SETFL,fl | O_NONBLOCK);//设置fd为非阻塞状态，且不影响其他选项
    return true;
}
int main()
{
///非阻塞IO
//1.open 函数的flag参数中有选项 O_NONBLOCK--打开的时候设定
//2.统一的方式设置--fcntl()函数

    //(1)
    SetNonBlock(0);//设置0号文件描述符为非阻塞状态---设置一次就不用在设置了
    char buffer[1024];
    while(true)
    {
        errno = 0;
        sleep(1);
        //阻塞IO
        //ssize_t s = read(0,buffer,sizeof(buffer)-1);
        //(2)非阻塞IO
        ssize_t s = read(0,buffer,sizeof(buffer)-1);//此时在进行读取，没有数据就会非阻塞轮询了
        //a.我们如何检测是真的调用失败出错还是没有数据就绪呢？
        //使用errno，如果出错不仅会返回，还会设置errno
        if(s>0)
        {
            buffer[s-1]=0;
            std::cout<<"echo: "<<buffer<<"--> errno:"<<errno<<"-->"<<strerror(errno)<<endl;
        }
        else{
            //errno==11表示底层数据没就绪，并非读取失败
            //cout<<"read \"error\""<<"--> errno:"<<errno<<"-->"<<strerror(errno)<<endl;
            if(errno==EWOULDBLOCK||errno==EAGAIN)
            {
                cout<<"数据未就绪，请重试"<<endl;
                continue;
            }
            else if(errno==EINTR)//信号被中断
            {
                cout<<"IO 可能被信号中断，请重试"<<endl;
                continue;
            }
            else{//真正的读取错误
                cout<<"read \"error\""<<"--> errno:"<<errno<<"-->"<<strerror(errno)<<endl;
            }
        }
        
    }
    return 0;
}